package com.atguigu.spring5.service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Transactional这个注解可以添加到类上面,也可以添加到方法上面
 * 添加到类上，为类里面所有的方法添加事务
 * 添加到方法上，为指定的方法添加注解
 * 参数:
 *
 * propagation: 事务传播行为
 *          (1) 多事务方法直接进行调用，这个过程中事务是如何进行管理的
 *              比如 当有事务的方法调用无事务的方法
 *                  有事务的方法调用有事务的方法
 *
 *              事务的传播行为是由传播属性决定的。Spring定义了7种类传播行为。
 *              传播属性
 *              REQUIRED                如果有事务在运行，当前的方法就在这个事务内运行，否则，就启动一个新的事务，并在自己的事务内运行。
 *              REQUIRED_NEW            当前的方法必须启动新事务，并在它自己的事务内运行，如果有事务正在运行，应该将它挂起。
 *
 *
 *              SUPPORTS                如果有事务在运行，当前的方法就在这个事务内运行，否则它可以不运行在事务中。
 *              NOT_SUPPORTED           当前的方法不应该运行在事务中，如果有运行的事务，将它挂起
 *
 *              NEVER                   当前的方法不应该运行在事务中，如果有运行的事务，就抛出异常。
 *              NESTED                  如果有事务在运行，当前的方法就应该在这个事务的嵌套事务内运行，否则，就启动一个新的事务，
 *                                      并在它自己的事务内运行。
 *
 *
 *
 * ioslation: 事务隔离级别
 *      (1) 事务有特性成为隔离级别，多事务操作之间不会产生影响。不考虑隔离性会产生很多问题。
 *      (2) 有三个读问题: 脏读，不可重复读，虚(幻)读
 *      (3) 脏读: 一个未提交事务读取到另一个未提交事务的数据。(致命问题)
 *      (4) 不可重复读: 一个未提交的事务读取到另一个提交事务修改数据(现象,允许产生)
 *      (5) 虚读: 一个未提交事务读取到另一提交事务添加数据
 *
 *      (6) 通过设置事务的隔离性,解决读的问题
 *
 *            READ UNCOMMITTED      脏读有     不可重复读有      幻读有
 *            (读未提交)
 *            READ COMMITTED        脏读无     不可重复读有      幻读有
 *            (读以提交)
 *            REPEATABLE READ       脏读无     不可重复读无      幻读有
 *            (可重复读,mysql默认级别)
 *            SERIALIZABLE          脏读无     不可重复读无      幻读无
 *             (串行化)
 *
 *
 * timeout: 超时时间
 *      (1) 事务需要在一定时间内进行提交，如果不提交进行回滚。
 *      (2) 默认值是-1,设置时间以秒为单位进行计算
 *
 * readOnly: 是否只读
 *      (1) 读: 查询操作,写: 添加修改删除操作
 *      (2) readOnly默认值 false,表示可以查询，可以添加修改删除
 *      (3) 设置readOnly值是true,设置成true,只能查询
 *
 * rollbackFor: 回滚
 *      (1) 设置出现哪些异常进行事务回滚
 *
 * noRollbackFor: 不回滚
 *      (1) 设置出现哪些异常不进行回滚
 *
 */
@Service
@Transactional(timeout = -1, propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
public class UserService {


    @Autowired
    private UserDao userDao;


    //编程时的异常处理
    //转账的方法
//    public void accountMoney() {
//
//        try {
//            //第一步开启事务
//
//
//            //第二步进行事务操作
//            //lucy少100
//            userDao.reduceMoney();
//
//            //模拟异常
//            int i = 10 / 0;
//
//            //mary多100
//            userDao.addMoney();
//
//            //第三步 没有发生异常,提交事务
//        } catch (Exception e) {
//            //第四步 出现异常,事务回滚
//        }
//
//    }


    public void accountMoney() {



            //lucy少100
            userDao.reduceMoney();

            //模拟异常
//            int i = 10 / 0;

            //mary多100
            userDao.addMoney();




    }


}
